package cn.iocoder.yudao.module.indicator.service.index;

import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.module.indicator.service.element.ElementCalculationService;
import cn.iocoder.yudao.module.indicator.base.ElementCalculationFactory;
import cn.iocoder.yudao.module.indicator.dao.element.DateListDao;
import cn.iocoder.yudao.module.indicator.domain.dto.IndexCalculationDto;
import cn.iocoder.yudao.module.indicator.domain.vo.DetailIndexCalculationVo;
import cn.iocoder.yudao.module.indicator.domain.vo.ElementCalculationVo;
import cn.iocoder.yudao.module.indicator.domain.vo.IndexCalculationVo;
import cn.iocoder.yudao.module.indicator.domain.vo.IndicatorVo;
import cn.iocoder.yudao.module.indicator.util.DateUtils;
import cn.iocoder.yudao.module.indicator.util.index.IndexCalculationUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @description  指标数据计算service
 * @author ZWC
 * @date 2024/9/26 16:35
 */
@Service
public class IndexCalculationServiceImpl implements IndexCalculationService {
    
    @Autowired
    private DateListDao dateListDao;

    @Autowired
    private ElementCalculationFactory elementCalculationFactory;

    @Autowired
    private IndicatorService indicatorServiceImpl;

    /**
     * 功能描述: 返回元素操作service，并且初始化指标返回对象
     * @param:
     * @return:
     * @author: ZWC
     * @date: 2024/10/21
     */
    public ElementCalculationService getElementCalculationService(IndexCalculationDto indexCalculationDto, IndexCalculationVo indexCalculationVo){
        // 查询指标信息
        IndicatorVo indicatorVo = indicatorServiceImpl.queryIndicatorById(indexCalculationDto.getIndexId());
        BeanUtil.copyProperties(indicatorVo, indexCalculationVo);
        //给元素id参数查询元素数据用
        indexCalculationDto.setElementIds(indexCalculationVo.getElementIds());
        // 根据指标的类型来获取相应的service
        return elementCalculationFactory.getElementService(indexCalculationVo.getSourceType());
    }
    @Override
    public IndexCalculationVo getIndex(IndexCalculationDto indexCalculationDto) {

        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        //查询元素的汇总数组，不管数据存在哪个表里，返回相同的数据格式
        List<ElementCalculationVo> elementListById = elementCalculationService.getElementById(indexCalculationDto);
        //查询指标值
        String indexValue = IndexCalculationUtil.getIndexValue(elementListById, indexCalculationVo);
        indexCalculationVo.setIndexNumber(indexValue);
        return indexCalculationVo;
    }

    /**
     * 功能描述: 计算同环比并获取上期和同期的指标数据
     * @param:
     * @return:
     * @author: ZWC
     * @date: 2024/10/22
     */
    @Override
    public IndexCalculationVo getIndexPreviousData(IndexCalculationDto indexCalculationDto) {

        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        // 查询元素的汇总数组，不管数据存在哪个表里，返回相同的数据格式
        // 查询本期指标值
        List<ElementCalculationVo> elementListById = elementCalculationService.getElementById(indexCalculationDto);
        if(!CollectionUtils.isEmpty(elementListById)){
            for (Long aLong : indexCalculationVo.getElementInfoMap().keySet()) {
                List<ElementCalculationVo> calculationVoList = elementListById.stream().filter(res -> res.getId().equals(aLong)).collect(Collectors.toList());
                String elementNumber = calculationVoList.get(0).getElementNumber();
                indexCalculationVo.getElementInfoMap().get(aLong).get(0).setElementNumber(elementNumber);
            }
        }
        String indexValue = IndexCalculationUtil.getIndexValue(elementListById, indexCalculationVo);
        indexCalculationVo.setIndexNumber(indexValue);
        if (Objects.equals(indexCalculationDto.getDateType(), indexCalculationDto.YEAR)){
            //是年就给上一年的数据
            if(!StringUtils.isEmpty(indexCalculationDto.getPeriodTime())) {
                String oldYear = DateUtils.getOldYear(indexCalculationDto.getPeriodTime(), -1);
                indexCalculationDto.setPeriodTime(oldYear);
                List<ElementCalculationVo> elementLastPeriod = elementCalculationService.getElementById(indexCalculationDto);
                String indexLastPeriodValue = IndexCalculationUtil.getIndexValue(elementLastPeriod, indexCalculationVo);
                //创建并放入上期指标数据
                DetailIndexCalculationVo lastPeriod = new DetailIndexCalculationVo();
                lastPeriod.setIndexNumber(indexLastPeriodValue);
                lastPeriod.setPeriodTime(oldYear);
                indexCalculationVo.setLastPeriodIndex(lastPeriod);
            }
        }else {
            // 给上期 和 同期的数据并返回
            if(!StringUtils.isEmpty(indexCalculationDto.getPeriodTime())) {
                // 计算上期数据
                String oldMonth = DateUtils.getOldMonth(indexCalculationDto.getPeriodTime(), -1);
                indexCalculationDto.setPeriodTime(oldMonth);
                List<ElementCalculationVo> elementLastPeriod = elementCalculationService.getElementById(indexCalculationDto);
                String indexLastPeriodValue = IndexCalculationUtil.getIndexValue(elementLastPeriod, indexCalculationVo);
                //创建并放入上期指标数据
                DetailIndexCalculationVo lastPeriod = new DetailIndexCalculationVo();
                lastPeriod.setIndexNumber(indexLastPeriodValue);
                lastPeriod.setPeriodTime(oldMonth);
                indexCalculationVo.setLastPeriodIndex(lastPeriod);

                // 计算同期数据
                String oldMonthSamePeriod = DateUtils.getOldMonth(indexCalculationDto.getPeriodTime(), -11);
                indexCalculationDto.setPeriodTime(oldMonthSamePeriod);
                List<ElementCalculationVo> elementSamePeriod = elementCalculationService.getElementById(indexCalculationDto);
                String indexSamePeriod = IndexCalculationUtil.getIndexValue(elementSamePeriod, indexCalculationVo);
                //创建并放入上期指标数据
                DetailIndexCalculationVo samePeriod = new DetailIndexCalculationVo();
                samePeriod.setIndexNumber(indexSamePeriod);
                samePeriod.setPeriodTime(oldMonthSamePeriod);
                indexCalculationVo.setSamePeriodIndex(samePeriod);

            }else {
                //查询计算同期数据 先设置同期开始与结束时间
                String oldStartTime = DateUtils.getOldMonth(indexCalculationDto.getStartTime(), -12);
                indexCalculationDto.setStartTime(oldStartTime);

                String oldEndTime = DateUtils.getOldMonth(indexCalculationDto.getEndTime(), -12);
                indexCalculationDto.setEndTime(oldEndTime);

                //查询同期数据
                List<ElementCalculationVo> elementSamePeriod = elementCalculationService.getElementById(indexCalculationDto);
                String indexSamePeriod = IndexCalculationUtil.getIndexValue(elementSamePeriod, indexCalculationVo);
                //创建并放入同期指标数据
                DetailIndexCalculationVo samePeriod = new DetailIndexCalculationVo();
                samePeriod.setIndexNumber(indexSamePeriod);
                samePeriod.setPeriodTime(oldStartTime + "~" + oldEndTime);
                indexCalculationVo.setSamePeriodIndex(samePeriod);
            }
        }
        // 返回结果
        return indexCalculationVo;
    }

    /**
     *
     * @param indexCalculationDto
     * @return
     */
    @Override
    public IndexCalculationVo getDeptIndex(IndexCalculationDto indexCalculationDto) {
        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        //获取指标的
        List<ElementCalculationVo> elementGroupInstitute = elementCalculationService.getElementGroupInstitute(indexCalculationDto);
        //查询指标值
        ArrayList<ElementCalculationVo> indexDeptListValue = IndexCalculationUtil.getIndexDeptValue(elementGroupInstitute, indexCalculationVo);
        indexCalculationVo.setElementCalculationVoList(indexDeptListValue);
        return indexCalculationVo;
    }


    @Override
    public IndexCalculationVo getDoctorIndex(IndexCalculationDto indexCalculationDto) {
        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        List<ElementCalculationVo> elementGroupDoctorList = elementCalculationService.getElementGroupDoctor(indexCalculationDto);
        ArrayList<ElementCalculationVo> indexDoctorValue = IndexCalculationUtil.getIndexDoctorValue(elementGroupDoctorList, indexCalculationVo);
        indexCalculationVo.setElementCalculationVoList(indexDoctorValue);
        return indexCalculationVo;
    }

    @Override
    public IndexCalculationVo getRoomIndex(IndexCalculationDto indexCalculationDto) {
        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        List<ElementCalculationVo> elementGroupDoctorList = elementCalculationService.getElementGroupRoom(indexCalculationDto);
        ArrayList<ElementCalculationVo> indexRoomValue = IndexCalculationUtil.getIndexRoomValue(elementGroupDoctorList, indexCalculationVo);
        indexCalculationVo.setElementCalculationVoList(indexRoomValue);
        return indexCalculationVo;
    }

    /**
     * 获取指标趋势的方法(至于查询哪个表元素数据，通过element工厂类进行划分,无论哪个表返回的元素都是统一格式，所以后续方法都一致)
     * @param indexCalculationDto
     * @return
     */
    @Override
    public IndexCalculationVo getIndexTrend(IndexCalculationDto indexCalculationDto) {
        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        List<String> dateList = dateList(indexCalculationDto);
        indexCalculationDto.setDateList(dateList);
        //            获取元素的数据
        List<ElementCalculationVo> elementTrend = elementCalculationService.getElementTrend(indexCalculationDto);
        // 处理元素
        List<ElementCalculationVo> indexTrendList = IndexCalculationUtil.getIndexTrend(elementTrend, indexCalculationVo, dateList);
        // 赋值
        indexCalculationVo.setElementCalculationVoList(indexTrendList);
        return indexCalculationVo;
    }

    @Override
    public IndexCalculationVo getElementTrend(IndexCalculationDto indexCalculationDto) {
        IndexCalculationVo indexCalculationVo = new IndexCalculationVo();
        ElementCalculationService elementCalculationService = getElementCalculationService(indexCalculationDto, indexCalculationVo);
        List<String> dateList = dateList(indexCalculationDto);
        indexCalculationDto.setDateList(dateList);
        List<ElementCalculationVo> elementTrend = elementCalculationService.getElementTrend(indexCalculationDto);
        indexCalculationVo.setElementCalculationVoList(elementTrend);
        return indexCalculationVo;
    }

    /**
     * 处理获取时间数组
     * @param indexCalculationDto
     * @return
     */
    private List<String> dateList(IndexCalculationDto indexCalculationDto){
        //获取时间数组
        List<String> dateList = new ArrayList<String>();
        if (Objects.equals(indexCalculationDto.getDateType(), indexCalculationDto.YEAR)) {
            if (!StringUtils.isEmpty(indexCalculationDto.getPeriodTime())) {
                //单独传年份
                dateList = dateListDao.getMonthByYear(indexCalculationDto.getPeriodTime());
                indexCalculationDto.setDateType(indexCalculationDto.MONTH);
            } else {
                //年份区间
                dateList = dateListDao.getYearSection(indexCalculationDto.getStartTime(), indexCalculationDto.getEndTime());
            }
        } else {
            if (!StringUtils.isEmpty(indexCalculationDto.getPeriodTime())) {
                dateList = dateListDao.getDayByMonth(indexCalculationDto.getPeriodTime());
                indexCalculationDto.setDateType(indexCalculationDto.DAY);
            } else {
                dateList = dateListDao.getMonthSection(indexCalculationDto.getStartTime(), indexCalculationDto.getEndTime());
            }
        }
        return dateList;
    }

    
}
